package com.wzdigit.wms.wms.service.core.inventory;


import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wzdigit.wms.basic.client.response.report.*;
import com.wzdigit.wms.basic.enums.InvReportEnum;
import com.wzdigit.wms.basic.mapper.core.basic.SkuMapper;
import com.wzdigit.wms.common.entity.ExcelExportConfig;
import com.wzdigit.wms.common.utils.HttpExcel;
import com.wzdigit.wms.basic.client.Pager;
import com.wzdigit.wms.basic.client.PagerInfo;
import com.wzdigit.wms.basic.client.request.report.LotInvReportSearchRequest;
import com.wzdigit.wms.basic.mapper.core.inventory.LotInvReportMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 整机仓位库存报表Service
 * Created by zyf on 2021/4/22 17:53
 */
@Service
@Slf4j
public class LotInvReportService {
    @Lazy
    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private LotInvReportMapper lotInvReportMapper;




    /**
     * 查询整机仓位库存报表信息
     *
     * @param search
     * @param pager
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<LotInvReportReponse>> searchSaleInvReport(
            LotInvReportSearchRequest search, Pager<?> pager){

        Page<LotInvReportReponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<LotInvReportReponse>> pagerInfo = new PagerInfo<>();
        try {
            List<LotInvReportReponse> datas =this.selectCommon(search);
            pagerInfo.setTotalCount(page.getTotal());
            pagerInfo.setItems(datas);
        }catch (Exception e){
            e.printStackTrace();
        }

        return pagerInfo;
    }

    /**
     * 导出整机仓位库存报表信息
     *
     * @param search
     * @param servletRequest
     * @param servletResponse
     * @return
     */
    @Transactional
    public void exportSaleInvReport(
            LotInvReportSearchRequest search,
            HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws Exception {
        ServletOutputStream out = null;
        XSSFWorkbook workbook = null;

        try{
            //设置导出信息
            List<LotInvReportReponse> datas =this.exportCommon(search);


            List<ExcelExportConfig> configs = new ArrayList<>();
            configs.add(new ExcelExportConfig("组织", "factory", 120));
            configs.add(new ExcelExportConfig("库存类型", "invType", 120));
            configs.add(new ExcelExportConfig("销售订单号", "soNo", 120));
            configs.add(new ExcelExportConfig("销售订单行号", "soItem", 120));
            configs.add(new ExcelExportConfig("订单号", "po", 120));
            configs.add(new ExcelExportConfig("业务部门", "businessDept", 120));
            configs.add(new ExcelExportConfig("业务科室", "businessSection", 120));
            configs.add(new ExcelExportConfig("国家", "country", 120));
            configs.add(new ExcelExportConfig("业务员", "businessMan", 120));
            configs.add(new ExcelExportConfig("仓库编码", "whsCode", 120));
            configs.add(new ExcelExportConfig("仓库名称", "whsName", 120));
            configs.add(new ExcelExportConfig("库区编码", "zoneCode", 120));
            configs.add(new ExcelExportConfig("库区名称", "zoneName", 120));
            configs.add(new ExcelExportConfig("外销原型机", "modelMechanic", 120));
            configs.add(new ExcelExportConfig("物料编码", "skuCode", 120));
            configs.add(new ExcelExportConfig("物料描述", "descCn", 120));
            configs.add(new ExcelExportConfig("品质状态", "qaStatus", 120));
            configs.add(new ExcelExportConfig("库存量", "invQtys", 120));
            configs.add(new ExcelExportConfig("库龄", "invAge", 120));
            workbook = HttpExcel.newListToExcel(datas, configs);
            String userAgent = servletRequest.getHeader("USER-AGENT");
            String fileName = "整机仓位库存报表";
            if (userAgent.contains("Mozilla")) {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "utf8");
            }
            servletResponse.setContentType("application/octet-stream");
            servletResponse.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ".xlsx");
            servletResponse.flushBuffer();
            out = servletResponse.getOutputStream();
            workbook.write(out);

        }catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
            if(workbook != null) {
                workbook.close();
            }
        }

    }

    private List<LotInvReportReponse> selectCommon(LotInvReportSearchRequest search){
        List<LotInvReportReponse> datas = lotInvReportMapper.selectAll(search);
        for (LotInvReportReponse data : datas) {
            //查询批次号
            List<String> lotnos = lotInvReportMapper.selectLotno(data.getSoNo(), data.getSoItem());
            //设置库存数量
            BigDecimal qtys =BigDecimal.ZERO;
            if (!CollectionUtil.isEmpty(lotnos)){
                BigDecimal searchQty = lotInvReportMapper.selectQty(data, lotnos);
                if (searchQty!=null){
                    qtys=qtys.add(searchQty);
                }
            }
            data.setInvQtys(qtys);
            //设置库龄
            data.setLastStockInDate(lotInvReportMapper.selectInvDate(data.getSoNo(),data.getSoItem()));
            if (data.getLastStockInDate()==null){
                data.setInvAge(0L);
            }else {
                data.setInvAge((new Date().getTime()-data.getLastStockInDate().getTime())/86400000);
            }
            //设置品质状态
            if (data.getQaStatusNumber()!=null){
                InvReportEnum invReportEnum = InvReportEnum.getEnumByCode(data.getQaStatusNumber());
                if (invReportEnum!=null){
                    data.setQaStatus(invReportEnum.getEnumName());
                }
            }
        }
        return datas;
    }

    private List<LotInvReportReponse> exportCommon(LotInvReportSearchRequest search){
        List<LotInvReportReponse> datas = lotInvReportMapper.selectAll(search);
        //查询库存信息
        List<InvGroupInfo> invGroupInfos = lotInvReportMapper.selectInvGroup();
        //查询销售+批次信息
        List<SoGroupInfo> soGroupInfos = lotInvReportMapper.selectSoGroup();
        //查询最晚入库时间信息
        List<DateGroupInfo> dateGroupInfos = lotInvReportMapper.selectDateGroup();
        //分组
        Map<String, List<InvGroupInfo>> invCollect = invGroupInfos.stream().collect(Collectors.groupingBy(t ->
                t.getFactory() + "#" + t.getWhsId() + "#" + t.getZoneId() + "#" + t.getSkuId()
                        + "#" + t.getLotno() + "#" + t.getQaStatusNumber()));
        Map<String, List<SoGroupInfo>> soCollect = soGroupInfos.stream().collect(Collectors.groupingBy(t ->
                t.getSoNo() + "#" + t.getSoItem()));
        Map<String, List<DateGroupInfo>> dateCollect = dateGroupInfos.stream().collect(Collectors.groupingBy(t ->
                t.getSoNo() + "#" + t.getSoItem()));
        for (LotInvReportReponse data : datas) {
            //获取批次号
            List<SoGroupInfo> soInfos = soCollect.get(data.getSoNo() + "#" + data.getSoItem());
            //设置库存数量
            BigDecimal qtys=BigDecimal.ZERO;
            if (!CollectionUtil.isEmpty(soInfos)){
                for (SoGroupInfo soInfo : soInfos) {
                    List<InvGroupInfo> inv = invCollect.get(data.getFactory() + "#" + data.getWhsId() + "#"
                            + data.getZoneId() + "#" + data.getSkuId()
                            + "#" + soInfo.getLotno() + "#" + data.getQaStatusNumber());
                    if (!CollectionUtil.isEmpty(inv)){
                        BigDecimal temp = inv.get(0).getQtys();
                        if (temp!=null){
                            qtys=qtys.add(temp);
                        }
                    }
                }
            }
            data.setInvQtys(qtys);
            //设置库龄
            List<DateGroupInfo> dateInfo = dateCollect.get(data.getSoNo() + "#" + data.getSoItem());
            if (dateInfo!=null){
                data.setLastStockInDate(dateInfo.get(0).getLastStockInDate());
            }
            if (data.getLastStockInDate()==null){
                data.setInvAge(0L);
            }else {
                data.setInvAge((new Date().getTime()-data.getLastStockInDate().getTime())/86400000);
            }
            //设置品质状态
            if (data.getQaStatusNumber()!=null){
                InvReportEnum invReportEnum = InvReportEnum.getEnumByCode(data.getQaStatusNumber());
                if (invReportEnum!=null){
                    data.setQaStatus(invReportEnum.getEnumName());
                }
            }
        }
        return datas;
    }


    //查询整机外销库存报表【新】
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PagerInfo<List<LotInvReportReponse>> searchSaleInvReportNew(
            LotInvReportSearchRequest search, Pager<?> pager){

        Page<LotInvReportReponse> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<LotInvReportReponse>> pagerInfo = new PagerInfo<>();
        try {
            List<LotInvReportReponse> datas =lotInvReportMapper.selectAllNew(search);
            for (LotInvReportReponse data : datas) {
                if (data.getQaStatusNumber()!=null){
                    InvReportEnum invReportEnum = InvReportEnum.getEnumByCode(data.getQaStatusNumber());
                    if (invReportEnum!=null){
                        data.setQaStatus(invReportEnum.getEnumName());
                    }
                }
            }
            pagerInfo.setTotalCount(page.getTotal());
            pagerInfo.setItems(datas);
        }catch (Exception e){
            e.printStackTrace();
        }

        return pagerInfo;
    }

    //导出整机库存报表【新】
    @Transactional
    public void exportSaleInvReportNew(
            LotInvReportSearchRequest search,
            HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws Exception {
        ServletOutputStream out = null;
        XSSFWorkbook workbook = null;

        try{
            //设置导出信息
            List<LotInvReportReponse> datas =lotInvReportMapper.selectAllNew(search);
            for (LotInvReportReponse data : datas) {
                if (data.getQaStatusNumber()!=null){
                    InvReportEnum invReportEnum = InvReportEnum.getEnumByCode(data.getQaStatusNumber());
                    if (invReportEnum!=null){
                        data.setQaStatus(invReportEnum.getEnumName());
                    }
                }
            }


            List<ExcelExportConfig> configs = new ArrayList<>();
            configs.add(new ExcelExportConfig("组织", "factory", 120));
            configs.add(new ExcelExportConfig("库存类型", "invType", 120));
            configs.add(new ExcelExportConfig("销售订单号", "soNo", 120));
            configs.add(new ExcelExportConfig("销售订单行号", "soItem", 120));
            configs.add(new ExcelExportConfig("订单号", "po", 120));
            configs.add(new ExcelExportConfig("业务部门", "businessDept", 120));
            configs.add(new ExcelExportConfig("业务科室", "businessSection", 120));
            configs.add(new ExcelExportConfig("国家", "country", 120));
            configs.add(new ExcelExportConfig("业务员", "businessMan", 120));
            configs.add(new ExcelExportConfig("仓库编码", "whsCode", 120));
            configs.add(new ExcelExportConfig("仓库名称", "whsName", 120));
            configs.add(new ExcelExportConfig("库区编码", "zoneCode", 120));
            configs.add(new ExcelExportConfig("库区名称", "zoneName", 120));
            configs.add(new ExcelExportConfig("外销原型机", "modelMechanic", 120));
            configs.add(new ExcelExportConfig("物料编码", "skuCode", 120));
            configs.add(new ExcelExportConfig("物料描述", "descCn", 120));
            configs.add(new ExcelExportConfig("品质状态", "qaStatus", 120));
            configs.add(new ExcelExportConfig("库存量", "invQtys", 120));
            configs.add(new ExcelExportConfig("库龄", "invAge", 120));
            workbook = HttpExcel.newListToExcel(datas, configs);
            String userAgent = servletRequest.getHeader("USER-AGENT");
            String fileName = "整机仓位库存报表";
            if (userAgent.contains("Mozilla")) {
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "utf8");
            }
            servletResponse.setContentType("application/octet-stream");
            servletResponse.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ".xlsx");
            servletResponse.flushBuffer();
            out = servletResponse.getOutputStream();
            workbook.write(out);

        }catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
            if(workbook != null) {
                workbook.close();
            }
        }

    }
    

}
